﻿// Inner Fire 游戏引擎库
// GameObject - 游戏对象
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 所属层级：应用层（4）
// 游戏最基础的对象，所有和模型有关的对象都继承自此类
// 也许在这个上面还要有一个更加基础的Object类。用于管理所有元素。
// 比如UI的Object也是需要一个GameObject。
// 但目前暂时这样。到时候看情况再进行重构。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-01-21

#include "game_object.h"
#include "klog.h"
#include <game/animation/animator.h>
#include <game/component/attacher.h>
#include <game/core/timer.h>
#include <game/physics/chara_controller.h>
#include <game/physics/collider.h>
#include <game/physics/physics_bone.h>
#include <game/physics/rigid_body.h>

namespace ifire::game {

static std::uint64_t uid_record = 10000000;

GameObject::GameObject(ikit::sstr name, Scene* scene, GameObject* parent)
    : scene_(scene)
    , parent_(parent)
    , uid(uid_record++)
    , name_(name)
    , transform_(this)
    , rigid_body(nullptr) {
  // 配置Transform的信息
  transform_.game_object = this;
  transform_.parent = parent == nullptr ? nullptr : &parent->GetTransform();
}

GameObject::~GameObject() {}

void GameObject::FixedUpdate() {
  float delta_time = g_timer.fixedDeltaTime;

  // 循环并执行每个Component的FixedUpdate
  for (auto& e : components_) {
    e->FixedUpdate(delta_time);
  }

  // 如果拥有Collider，则设置Collider碰撞体缓存为False，刷新碰撞体
  if (collider){
    collider->MarkDirty();
  }
}

void GameObject::LateUpdate() {
  float delta_time = g_timer.fixedDeltaTime;

  // 循环并执行每个Component的LateUpdate
  for (auto& e : components_) {
    e->LateUpdate(delta_time);
  }

  // 如果拥有Collider，并且拥有视觉对象，则更新
  if (collider && collider->HasVisualObject()){
    collider->UpdateVisualObject();
  }
}

Armature* GameObject::GetArmature() { return nullptr; }

dx::SkinAnimator* GameObject::GetSkinAnimator() { return nullptr; }

void GameObject::PrintInfo(ikit::sstr info_type) {
  static const ikit::sstr TYPE_NAME("Name");

  if (info_type == TYPE_NAME) {
    ikit::log("GameObject: %s", name_.c_str());
  }
}

void GameObject::UpdateTransform() { transform_.BuildMatrix(); }

void GameObject::SetRenderMatrix(FMat mat) {}

Component* GameObject::AddComponent(ikit::sstr component_type) {
  if (component_type == Animator::ComponentType()) {
    auto item = std::make_unique<Animator>(this);
    return AddComponent(std::move(item));
  } else if (component_type == Attacher::ComponentType()) {
    auto item = std::make_unique<Attacher>(this);
    return AddComponent(std::move(item));
  } else if (component_type == CharaController::ComponentType()) {
    auto item = std::make_unique<CharaController>(this);
    return AddComponent(std::move(item));
  } else if (component_type == PhysicsBone::ComponentType()) {
    auto item = std::make_unique<PhysicsBone>(this);
    return AddComponent(std::move(item));
  }

  return nullptr;
}

Component* GameObject::AddComponent(ComponentPtr comp) {
  Component* ptr = comp.get();
  components_.push_back(std::move(comp));
  return ptr;
}

Component* GameObject::GetComponent(ikit::sstr component_type) {
  for (auto& e : components_) {
    if (e->IsType(component_type)) {
      return e.get();
    }
  }
  return nullptr;
}

RigidBody* GameObject::AddRigidBody() {
  if (!rigid_body) {
    rigid_body = std::make_unique<RigidBody>(this);
  }
  return rigid_body.get();
}

Collider* GameObject::AddCollider() {
  if (!collider) {
    collider = std::make_unique<Collider>(this);
  }
  return collider.get();
}

void GameObject::SetPosition(IVec3 position) {
  transform_.SetPosition(position);
  UpdateTransform();
}

void GameObject::SetRotation(IVec3 rotation) {
  transform_.SetRotationEular(rotation);
  UpdateTransform();
}

void GameObject::SetScale(IVec3 scale) {
  transform_.SetScale(scale);
  UpdateTransform();
}

void GameObject::AttachLuaObject(ikit::sstr name, int register_index) {
  lua_objects_[name.uid()] = register_index;
}

int GameObject::GetLuaObject(ikit::sstr name) {
  return lua_objects_[name.uid()];
}

void GameObject::SetParent(GameObject* parent) {
  parent_ = parent;
  // 当Object的Parent改变的时候，Transform的Parent也会改变
  transform_.parent = parent == nullptr ? nullptr : &parent->GetTransform();
}

} // namespace ifire::game
